#pragma once

#include <AVUIPropertyMetadata.h>
#include <AVUIExceptions.h>

namespace AVUI {

class UIPropertyMetadata : public PropertyMetadata
{
public:
    DECLARE_ELEMENT(UIPropertyMetadata, PropertyMetadata);

#pragma region Public Methods

    /// <summary> Initializes a new instance of the <see cref="T:System.Windows.UIPropertyMetadata" /> class. </summary>
    UIPropertyMetadata() { }

    /// <summary> Initializes a new instance of the <see cref="T:System.Windows.UIPropertyMetadata" /> class, with the specified default value for the property.</summary>
    /// <param name="defaultValue">The default value of the dependency property, usually provided as a value of some specific type.</param>
    UIPropertyMetadata(Object* pDefaultValue) : PropertyMetadata(pDefaultValue) { };

    /// <summary> Initializes a new instance of the <see cref="T:System.Windows.UIPropertyMetadata" /> class, with the specified PropertyChanged callback.</summary>
    /// <param name="propertyChangedCallback">Reference to a handler implementation that is to be called by the property system whenever the effective value of the property changes.</param>
    UIPropertyMetadata(PropertyChangedCallback propertyChangedCallback) : PropertyMetadata(propertyChangedCallback) { };

    /// <summary> Initializes a new instance of the <see cref="T:System.Windows.PropertyMetadata" /> class with the specified default value and <see cref="T:System.Windows.PropertyChangedCallback" /> implementation reference. </summary>
    /// <param name="defaultValue">The default value of the dependency property, usually provided as a value of some specific type.</param>
    /// <param name="propertyChangedCallback">Reference to a handler implementation that is to be called by the property system whenever the effective value of the property changes.</param>
    /// <exception cref="T:System.ArgumentException">
    /// <paramref name="defaultValue" /> cannot be set to the value <see cref="F:System.Windows.DependencyProperty.UnsetValue" />; see Remarks.</exception>
    UIPropertyMetadata(Object* pDefaultValue, PropertyChangedCallback propertyChangedCallback) : PropertyMetadata(pDefaultValue, propertyChangedCallback) { };

    /// <summary> Initializes a new instance of the <see cref="T:System.Windows.UIPropertyMetadata" /> class, with the specified default value and callbacks. </summary>
    /// <param name="defaultValue">The default value of the dependency property, usually provided as a value of some specific type.</param>
    /// <param name="propertyChangedCallback">Reference to a handler implementation that is to be called by the property system whenever the effective value of the property changes.</param>
    /// <param name="coerceValueCallback">Reference to a handler implementation that is to be called whenever the property system calls <see cref="M:System.Windows.DependencyObject.CoerceValue(System.Windows.DependencyProperty)" /> against this property.</param>
    UIPropertyMetadata(Object* pDefaultValue, PropertyChangedCallback propertyChangedCallback, CoerceValueCallback coerceValueCallback) : PropertyMetadata(pDefaultValue, propertyChangedCallback, coerceValueCallback) { };

    /// <summary> Initializes a new instance of the <see cref="T:System.Windows.UIPropertyMetadata" /> class, with the specified default value and callbacks, and a Boolean used to disable animations on the property. </summary>
    /// <param name="defaultValue">The default value of the dependency property, usually provided as a value of some specific type.</param>
    /// <param name="propertyChangedCallback">Reference to a handler implementation that is to be called by the property system whenever the effective value of the property changes.</param>
    /// <param name="coerceValueCallback">Reference to a handler implementation that is to be called whenever the property system calls <see cref="M:System.Windows.DependencyObject.CoerceValue(System.Windows.DependencyProperty)" /> against this property.</param>
    /// <param name="isAnimationProhibited">Set to true to prevent the property system from animating the property that this metadata is applied to. Such properties will raise run time exceptions if animations of them are attempted. The default is false.</param>
    UIPropertyMetadata(Object* pDefaultValue, PropertyChangedCallback propertyChangedCallback, CoerceValueCallback coerceValueCallback, bool isAnimationProhibited) : PropertyMetadata(pDefaultValue, propertyChangedCallback, coerceValueCallback) 
    { 
        WriteFlag(PropertyMetadata::MetadataFlags::UI_IsAnimationProhibitedID, isAnimationProhibited);
    };

#pragma endregion Public Methods
 
#pragma region Public Properties

    /// <summary> Gets or sets a value declaring whether animations should be disabled on the dependency property where the containing metadata instance is applied. </summary>
    /// <returns>true indicates that animations are disallowed; false indicates that animations are allowed. The default is false (animations allowed).</returns>
    bool get_IsAnimationProhibited()
    {
        return ReadFlag(PropertyMetadata::MetadataFlags::UI_IsAnimationProhibitedID);
    }
    void set_IsAnimationProhibited(bool value)
    {
        if (get_Sealed())
        {
            LibraryThrowException(object_allocate<InvalidOperationException>("Type metadata cannot change after use."));
        }
        WriteFlag(PropertyMetadata::MetadataFlags::UI_IsAnimationProhibitedID, value);
    }

#pragma endregion Public Properties
 
protected:

public:

#pragma region Internal Methods

    TRefCountedPtr<PropertyMetadata> CreateInstance() AVUI_OVERRIDE
    {
        return (PropertyMetadata*)object_allocate<UIPropertyMetadata>();
    }

#pragma endregion Internal Methods

};

}; // namespace AVUI

